package pricing

import (
	"errors"
	"fmt"
	"log"
	"sort"
	"time"

	"github.com/ev-charging/cloud-platform/config"
)

// TimeRange 表示一天中的时间段
type TimeRange struct {
	StartHour int `json:"start_hour"`
	StartMin  int `json:"start_min"`
	EndHour   int `json:"end_hour"`
	EndMin    int `json:"end_min"`
}

// PricingEngine 电价策略引擎
type PricingEngine struct {
	defaultRate    float64                // 默认电价
	timeRanges     []config.TimeRangeRate // 分时电价配置
	timeRangeRates map[string]float64     // 时间段到电价的映射
}

// parseTime 解析时间字符串（如 "22:00"）为小时和分钟
func parseTime(timeStr string) (int, int, error) {
	var hour, min int
	_, err := fmt.Sscanf(timeStr, "%d:%d", &hour, &min)
	if err != nil {
		return 0, 0, fmt.Errorf("invalid time format: %s", timeStr)
	}
	return hour, min, nil
}

// NewPricingEngine 创建新的电价策略引擎
func NewPricingEngine(cfg *config.PricingConfig) *PricingEngine {
	// 预先解析时间字段
	for i := range cfg.TimeRanges {
		tr := &cfg.TimeRanges[i]
		h1, m1, _ := parseTime(tr.Start)
		h2, m2, _ := parseTime(tr.End)
		tr.StartHour = h1
		tr.StartMin = m1
		tr.EndHour = h2
		tr.EndMin = m2
	}

	engine := &PricingEngine{
		defaultRate:    cfg.DefaultRate,
		timeRanges:     cfg.TimeRanges,
		timeRangeRates: make(map[string]float64),
	}

	engine.initializeTimeRangeRates()

	return engine
}

// initializeTimeRangeRates 初始化时间段到电价的映射
func (e *PricingEngine) initializeTimeRangeRates() {
	for _, tr := range e.timeRanges {
		key := fmt.Sprintf("%02d:%02d-%02d:%02d", tr.StartHour, tr.StartMin, tr.EndHour, tr.EndMin)
		e.timeRangeRates[key] = tr.Rate
	}
}

// GetRateByTime 根据时间获取电价
func (e *PricingEngine) GetRateByTime(t time.Time) float64 {
	hour := t.Hour()
	min := t.Minute()

	for _, tr := range e.timeRanges {
		startHour := tr.StartHour
		startMin := tr.StartMin
		endHour := tr.EndHour
		endMin := tr.EndMin

		if startHour > endHour {
			if (hour > startHour || (hour == startHour && min >= startMin)) ||
				(hour < endHour || (hour == endHour && min <= endMin)) {
				return tr.Rate
			}
		} else {
			if (hour > startHour || (hour == startHour && min >= startMin)) &&
				(hour < endHour || (hour == endHour && min <= endMin)) {
				return tr.Rate
			}
		}
	}

	return e.defaultRate
}

// CalculateCost 计算充电费用
func (e *PricingEngine) CalculateCost(energy float64, startTime, endTime time.Time) (float64, error) {
	if energy <= 0 {
		return 0, errors.New("用电量必须大于0")
	}

	if startTime.After(endTime) {
		return 0, errors.New("开始时间不能晚于结束时间")
	}

	// 如果充电时间在同一个小时内
	if startTime.Day() == endTime.Day() && startTime.Hour() == endTime.Hour() {
		rate := e.GetRateByTime(startTime)
		return energy * rate, nil
	}

	// 如果充电跨多个时间段，需要分段计算
	// 这里简化处理，按小时分段
	var totalCost float64
	currentTime := startTime

	for currentTime.Before(endTime) {
		// 获取当前小时的电价
		currentRate := e.GetRateByTime(currentTime)

		// 计算当前小时内的充电时长（分钟）
		nextHour := currentTime.Add(time.Hour).Truncate(time.Hour)
		var duration time.Duration

		if nextHour.After(endTime) {
			duration = endTime.Sub(currentTime)
		} else {
			duration = nextHour.Sub(currentTime)
		}

		// 按比例计算当前小时的用电量
		hours := duration.Hours()
		energyRatio := hours / endTime.Sub(startTime).Hours()
		currentEnergy := energy * energyRatio

		// 累加费用
		totalCost += currentEnergy * currentRate

		currentTime = nextHour
	}

	return totalCost, nil
}

// GetTimeRanges 获取所有时间段配置
func (e *PricingEngine) GetTimeRanges() []config.TimeRangeRate {
	sortedRanges := make([]config.TimeRangeRate, len(e.timeRanges))
	copy(sortedRanges, e.timeRanges)

	sort.Slice(sortedRanges, func(i, j int) bool {
		return sortedRanges[i].StartHour < sortedRanges[j].StartHour ||
			(sortedRanges[i].StartHour == sortedRanges[j].StartHour &&
				sortedRanges[i].StartMin < sortedRanges[j].StartMin)
	})

	return sortedRanges
}

// UpdateRates 更新电价配置
func (e *PricingEngine) UpdateRates(cfg *config.PricingConfig) {
	e.defaultRate = cfg.DefaultRate
	e.timeRanges = cfg.TimeRanges
	e.initializeTimeRangeRates()
	log.Println("电价配置已更新")
}
